

#ifndef CROX_VALUE_H
#define CROX_VALUE_H

#include "common.h"

typedef struct RoxObj Obj;
typedef struct RoxObjString ObjString;

typedef enum {
    VAL_BOOL,
    VAL_NULL,
    VAL_NUMBER,
    VAL_OBJ,
} ValueType;

typedef struct {
    ValueType type;
    union {
        bool boolean;
        double number;
        Obj* obj;
    } as;
} Value;

#define IS_BOOL(value) ((value.type) == VAL_BOOL)
#define IS_NULL(value) ((value.type) == VAL_NULL)
#define IS_NUMBER(value) ((value.type) == VAL_NUMBER)
#define IS_OBJ(value) ((value.type) == VAL_OBJ)

#define AS_BOOL(value) ((value).as.boolean)
#define AS_NUMBER(value) ((value).as.number)
#define AS_OBJ(value) ((value).as.obj)

#define BOOL_VAL(value)  ((Value) {VAL_BOOL, {.boolean = value}})
#define NULL_VAL  ((Value) {VAL_NULL, {.number = 0}})
#define NUMBER_VAL(value)  ((Value) {VAL_NUMBER, {.number = value}})
#define OBJ_VAL(o) ((Value) {VAL_OBJ, {.obj = (Obj*) o}})

typedef struct {
    int capacity;
    int size;
    Value *values;
} ValueArray;

bool valuesEqual(Value a, Value b);

void initValueArray(ValueArray *array);

int writeValueArray(ValueArray *array, Value value);

void freeValueArray(ValueArray *array);

void printValue(Value value);

#endif //CROX_VALUE_H
